package com.cacche.thread;

import java.util.HashMap;
import java.util.LinkedList;

/**
 * 线程池 创建线程池，销毁线程池，添加新任务
 * 
 * @ClassName: ThreadPool
 * @Description: TODO(这里用一句话描述这个类的作用)
 * @author 刘章
 * @date 2013-7-2 下午5:28:12
 * 
 */
public final class ThreadPool
{
	/* 单例 */
	private static ThreadPool              instance               = null;
	
	private static final int               SYSTEM_BUSY_TASK_COUNT = 15;
	/* 默认池中线程数 */
	private static int                     worker_num             = 2;
	
	public static boolean                  systemIsBusy           = false;
	private static HashMap<String, String> taskMap                = new HashMap<String, String>();
	private static LinkedList<ThreadTask>  taskQueue              = new LinkedList<ThreadTask>();
	/* 池中的所有线程 */
	private PoolWorker[]                   workers;
	
	private ThreadPool() {
		workers = new PoolWorker[worker_num];
		for (int i = 0; i < workers.length; i++)
		{
			workers[i] = new PoolWorker(i);
		}
	}
	
	private ThreadPool(int pool_worker_num) {
		worker_num = pool_worker_num;
		workers = new PoolWorker[worker_num];
		for (int i = 0; i < workers.length; i++)
		{
			workers[i] = new PoolWorker(i);
		}
	}
	
	public static synchronized ThreadPool getInstance() {
		if (instance == null)
		{
			instance = new ThreadPool();
		}
		return instance;
	}
	
	/**
	 * 增加新的任务 每增加一个新任务，都要唤醒任务队列
	 * 
	 * @param newTask
	 */
	public void addTask(ThreadTask newTask) {
		if (!taskMap.containsKey(newTask.getTaskId()))
		{
			synchronized (taskQueue)
			{
				if (taskQueue.size() > SYSTEM_BUSY_TASK_COUNT)
				{
					taskMap.remove(taskQueue.removeFirst().getTaskId());
				}
				taskMap.put(newTask.getTaskId(), newTask.getTaskId());
				taskQueue.addLast(newTask);
				/* 唤醒队列, 开始执行 */
				taskQueue.notifyAll();
			}
		}
	}
	
	/**
	 * 批量增加新任务
	 * 
	 * @param taskes
	 */
	public void batchAddTask(ThreadTask[] taskes) {
		if (taskes == null || taskes.length == 0) { return; }
		synchronized (taskQueue)
		{
			for (int i = 0; i < taskes.length; i++)
			{
				if (taskes[i] == null)
				{
					continue;
				}
				if (taskQueue.size() > SYSTEM_BUSY_TASK_COUNT)
				{
					taskMap.remove(taskQueue.removeFirst().getTaskId());
				}
				taskMap.put(taskes[i].getTaskId(), taskes[i].getTaskId());
				taskQueue.addLast(taskes[i]);
			}
			/* 唤醒队列, 开始执行 */
			taskQueue.notifyAll();
		}
	}
	
	/**
	 * 线程池信息
	 * 
	 * @return
	 */
	public String getInfo() {
		StringBuffer sb = new StringBuffer();
		sb.append("\nTask Queue Size:" + taskQueue.size());
		for (int i = 0; i < workers.length; i++)
		{
			sb.append("\nWorker " + i + " is " + ((workers[i].isWaiting()) ? "Waiting." : "Running."));
		}
		return sb.toString();
	}
	
	/**
	 * 销毁线程池
	 */
	public synchronized void destroy() {
		for (int i = 0; i < worker_num; i++)
		{
			workers[i].stopWorker();
			workers[i] = null;
		}
		taskQueue.clear();
		taskMap.clear();
	}
	
	/**
	 * 池中工作线程
	 * 
	 * @author obullxl
	 */
	private class PoolWorker
	        extends
	        Thread
	{
		private int     index     = -1;
		/* 该工作线程是否有效 */
		private boolean isRunning = true;
		/* 该工作线程是否可以执行新任务 */
		private boolean isWaiting = true;
		
		public PoolWorker(int index) {
			this.index = index;
			start();
		}
		
		public void stopWorker() {
			this.isRunning = false;
		}
		
		public boolean isWaiting() {
			return this.isWaiting;
		}
		
		/**
		 * 循环执行任务 这也许是线程池的关键所在
		 */
		public void run() {
			while (isRunning)
			{
				Thread thread = null;
				ThreadTask r = null;
				synchronized (taskQueue)
				{
					while (taskQueue.isEmpty())
					{
						try
						{
							/* 任务队列为空，则等待有新任务加入从而被唤醒 */
							taskQueue.wait(20);
						}
						catch (InterruptedException ie)
						{
							ie.printStackTrace();
						}
					}
					/* 取出任务执行 */
					r = (ThreadTask) taskQueue.removeLast();
				}
				if (r != null)
				{
					try
					{
						isWaiting = false;
						/* 该任务是否需要立即执行 */
						r.setBeginExceuteTime();
						if (r.needExecuteImmediate())
						{
							thread = new Thread(r);
							thread.start();
						}
						else
						{
							r.run();
						}
						r.setFinishTime();
					}
					catch (Exception e)
					{
						e.printStackTrace();
					}
					finally
					{
						taskMap.remove(r.getTaskId());
						isWaiting = true;
						r.log(index);
						if (!r.needExecuteImmediate())
						{
							r = null;
						}
					}
				}
			}
		}
	}
}
